﻿using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using WickedSick.ClientComponents.Music;

namespace SDB
{
    [TemplatePart(Name="PART_PreviousButton", Type=typeof(ButtonBase))]
    [TemplatePart(Name="PART_StopButton", Type=typeof(ButtonBase))]
    [TemplatePart(Name="PART_PlayPauseButton", Type=typeof(ButtonBase))]
    [TemplatePart(Name="PART_NextButton", Type=typeof(ButtonBase))]
    [TemplatePart(Name="PART_Shuffle", Type=typeof(ToggleButton))]
    [TemplatePart(Name="PART_Repeat", Type=typeof(ToggleButton))]
    public partial class SongPlayer : UserControl
    {
        private KeyboardHook _KeyHook;
        private bool _KeyboardHookInstalled;
        private PlaybackManager _PlayManager;
        private string _BaseMediaDirectory;

        public static readonly RoutedEvent PreviousTrackClickEvent =
            EventManager.RegisterRoutedEvent("PreviousTrackClick", RoutingStrategy.Bubble,
            typeof(MediaButtonClickEventHandler), typeof(SongPlayer));

        public static readonly RoutedEvent StopClickEvent =
            EventManager.RegisterRoutedEvent("StopClick", RoutingStrategy.Bubble,
            typeof(MediaButtonClickEventHandler), typeof(SongPlayer));

        public static readonly RoutedEvent PlayPauseClickEvent =
            EventManager.RegisterRoutedEvent("PlayPauseClick", RoutingStrategy.Bubble,
            typeof(MediaButtonClickEventHandler), typeof(SongPlayer));

        public static readonly RoutedEvent NextTrackClickEvent =
            EventManager.RegisterRoutedEvent("NextTrackClick", RoutingStrategy.Bubble,
            typeof(MediaButtonClickEventHandler), typeof(SongPlayer));

        public static readonly DependencyProperty MaxLocalStorageProperty = 
            DependencyProperty.Register("MaxLocalStorage", typeof(long),
            typeof(SongPlayer), new PropertyMetadata((long)1073741824));

        public static readonly DependencyProperty CopyLocalEnabledProperty =
            DependencyProperty.Register("CopyLocalEnabled", typeof(bool), typeof(SongPlayer),
            new PropertyMetadata(true));

        public event MediaButtonClickEventHandler PreviousTrackClick
        {
            add
            {
                AddHandler(PreviousTrackClickEvent, value);
            }
            remove
            {
                RemoveHandler(PreviousTrackClickEvent, value);
            }
        }

        public event MediaButtonClickEventHandler StopClick
        {
            add
            {
                AddHandler(StopClickEvent, value);
            }
            remove
            {
                RemoveHandler(StopClickEvent, value);
            }
        }

        public event MediaButtonClickEventHandler PlayPauseClick
        {
            add
            {
                AddHandler(PlayPauseClickEvent, value);
            }
            remove
            {
                RemoveHandler(PlayPauseClickEvent, value);
            }
        }

        public event MediaButtonClickEventHandler NextTrackClick
        {
            add
            {
                AddHandler(NextTrackClickEvent, value);
            }
            remove
            {
                RemoveHandler(NextTrackClickEvent, value);
            }
        }

        public SongPlayer()
        {
            InitializeComponent();
            
            ButtonBase prev = (ButtonBase)FindName("PART_PreviousButton");
            if (prev != null)
            {
                prev.Click += new RoutedEventHandler(prev_Click);
            }
            ButtonBase stop = (ButtonBase)FindName("PART_StopButton");
            if (stop != null)
            {
                stop.Click += new RoutedEventHandler(stop_Click);
            }
            ButtonBase playpause = (ButtonBase)FindName("PART_PlayPauseButton");
            if (playpause != null)
            {
                playpause.Click += new RoutedEventHandler(playpause_Click);
            }
            ButtonBase next = (ButtonBase)FindName("PART_NextButton");
            if (next != null)
            {
                next.Click += new RoutedEventHandler(next_Click);
            }
            ToggleButton shuffle = (ToggleButton)FindName("PART_Shuffle");
            if (shuffle != null)
            {
                shuffle.Checked += new RoutedEventHandler(shuffle_Checked);
                shuffle.Unchecked += new RoutedEventHandler(shuffle_Unchecked);
            }
            ToggleButton repeat = (ToggleButton)FindName("PART_Repeat");
            if (repeat != null)
            {
                repeat.Checked += new RoutedEventHandler(repeat_Checked);
                repeat.Unchecked += new RoutedEventHandler(repeat_Unchecked);
            }

            try
            {
                _KeyHook = new KeyboardHook();
                _KeyHook.KeyDown += new KeyboardHook.HookEventHandler(_KeyHook_KeyDown);
                _KeyboardHookInstalled = true;
            }
            catch
            {
                _KeyboardHookInstalled = false;
            }

            if (string.IsNullOrEmpty(_BaseMediaDirectory))
            {
                _BaseMediaDirectory = Environment.CurrentDirectory;
            }
            _PlayManager = new PlaybackManager(_MediaPlayer, _BaseMediaDirectory, CopyAllowed);
            
        }

        private bool CopyAllowed(long file_length)
        {
            long cur_size = 0;
            foreach (FileInfo info in (new DirectoryInfo(BaseMediaDirectory)).GetFiles(".mp3", SearchOption.AllDirectories))
            {
                cur_size += info.Length;
            }
            if (cur_size + file_length > MaxLocalStorage)
            {
                return false;
            }

            if (!CopyLocalEnabled)
                return false;

            return true;
        }

        private void shuffle_Checked(object sender, RoutedEventArgs e)
        {
            _PlayManager.IsRandom = true;
        }

        private void shuffle_Unchecked(object sender, RoutedEventArgs e)
        {
            _PlayManager.IsRandom = false;
        }

        private void repeat_Checked(object sender, RoutedEventArgs e)
        {
            _PlayManager.IsRepeat = true;
        }

        private void repeat_Unchecked(object sender, RoutedEventArgs e)
        {
            _PlayManager.IsRepeat = false;
        }

        #region PROPERTIES

        public bool IsKeyboardHookInstalled
        {
            get { return _KeyboardHookInstalled; }
        }

        public bool IsPlaying
        {
            get
            {
                return !_MediaPlayer.Clock.IsPaused;
            }
        }

        public MediaClock Clock
        {
            get { return _MediaPlayer.Clock; }
        }

        public string BaseMediaDirectory
        {
            get { return _BaseMediaDirectory; }
            set { _BaseMediaDirectory = value; }
        }

        public PlaybackManager SongManager
        {
            get { return _PlayManager; }
        }

        public long MaxLocalStorage
        {
            get 
            {
                //returned # of bytes as long
                return (long)GetValue(MaxLocalStorageProperty);
            }
            set 
            {
                //saved as # of mb
                SetValue(MaxLocalStorageProperty, (long)value);
            }
        }

        public bool CopyLocalEnabled
        {
            get { return (bool)GetValue(CopyLocalEnabledProperty); }
            set { SetValue(CopyLocalEnabledProperty, value); }
        }

        #endregion

        #region MEDIA CONTROLS

        private void prev_Click(object sender, RoutedEventArgs e)
        {
            CallPrevious();
        }

        private void stop_Click(object sender, RoutedEventArgs e)
        {
            CallStop();
        }

        private void playpause_Click(object sender, RoutedEventArgs e)
        {
            CallPlayPause();
        }

        private void next_Click(object sender, RoutedEventArgs e)
        {
            CallNext();
        }

        private void _KeyHook_KeyDown(object sender, HookEventArgs e)
        {
            if (e.Key == System.Windows.Forms.Keys.MediaPreviousTrack)
            {
                CallPrevious();
            }
            else if (e.Key == System.Windows.Forms.Keys.MediaStop)
            {
                CallStop();
            }
            else if (e.Key == System.Windows.Forms.Keys.MediaPlayPause)
            {
                CallPlayPause();
            }
            else if (e.Key == System.Windows.Forms.Keys.MediaNextTrack)
            {
                CallNext();
            }
        }

        private void CallPrevious()
        {
            _PlayManager.Previous();
            RaiseEvent(new MediaButtonClickEventArgs(PreviousTrackClickEvent,
                this, MediaButtons.PreviousTrack));
        }
        
        private void CallStop()
        {
            _PlayManager.Stop();
            RaiseEvent(new MediaButtonClickEventArgs(StopClickEvent,
                this, MediaButtons.Stop));
        }

        private void CallPlayPause()
        {
            _PlayManager.TogglePlay();
            RaiseEvent(new MediaButtonClickEventArgs(PlayPauseClickEvent,
                this, MediaButtons.PlayPause));
        }
        
        private void CallNext()
        {
            _PlayManager.Next();
            RaiseEvent(new MediaButtonClickEventArgs(NextTrackClickEvent,
                this, MediaButtons.NextTrack));
        }

        #endregion
    }

    public delegate void MediaButtonClickEventHandler(object sender, MediaButtonClickEventArgs e);

    public enum MediaButtons
    {
        PreviousTrack,
        Stop,
        PlayPause,
        NextTrack
    }

    public class MediaButtonClickEventArgs : RoutedEventArgs
    {
        private MediaButtons _MediaButton;

        public MediaButtonClickEventArgs(RoutedEvent routedEvent, object source, MediaButtons button)
            : base(routedEvent, source)
        {
            this.MediaButton = button;
        }

        public MediaButtons MediaButton
        {
            get { return _MediaButton; }
            set { _MediaButton = value; }
        }
    }
}